package com.tbit.uqbike.service.business.impl;

import com.alibaba.fastjson.JSON;
import com.tbit.common.constant.OperationPlatform;
import com.tbit.common.entity.UserOpLog;
import com.tbit.common.entity.view.Result;
import com.tbit.uqbike.enums.SystemCodeEnum;
import com.tbit.uqbike.manager.exception.BaseException;
import com.tbit.uqbike.object.business.UserInfo;
import com.tbit.uqbike.object.pojo.*;
import com.tbit.uqbike.object.pojo.dto.GiftCardBatchUpdateDTO;
import com.tbit.uqbike.object.pojo.vo.GiftCardVO;
import com.tbit.uqbike.object.pojo.vo.GiveRideCardVo;
import com.tbit.uqbike.object.value.LoginInfo;
import com.tbit.uqbike.service.business.AccountService;
import com.tbit.uqbike.service.business.GiftCardService;
import com.tbit.uqbike.service.business.GiftCardUserService;
import com.tbit.uqbike.service.business.UserService;
import com.tbit.uqbike.service.rpcservice.PurviewService;
import com.tbit.uqbike.webmanager.business.user_op_log.service.UserOpLogService;
import com.tbit.uqbike.webmanager.controller.BaseController;
import com.tbit.uqbike.webmanager.dao.core.CouponDao;
import com.tbit.uqbike.webmanager.dao.core.GiftCardDao;
import com.tbit.uqbike.webmanager.dao.core.UsermsgDao;
import com.tbit.uqbike.webmanager.util.MD5PasswordUtil;
import com.tbit.uqbike.webmanager.util.NumberUtils;
import com.tbit.utils.DateTimeUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;

/**
 * @author chenmengran
 * @Description: 礼品卡
 * @date 2019\12\28 002815:00
 */
@Service
@Slf4j
public class GiftCardServiceImpl implements GiftCardService {
    @Autowired
    private GiftCardDao giftCardDao;
    @Autowired
    private PurviewService purviewService;
    @Autowired
    private UserService userService;
    @Autowired
    private AccountService accountService;
    @Autowired
    private GiftCardUserService giftCardUserService;
    @Autowired
    private UsermsgDao usermsgDao;
    @Autowired
    private CouponDao couponDao;
    @Autowired
    private UserOpLogService userOpLogService;

    @Override
    public void addEdit(LoginInfo loginInfo, GiftCard giftCard) {
        if (!purviewService.purviewCheck(loginInfo.id, giftCard.getAccountId())) {
            throw new BaseException(SystemCodeEnum.NO_PRIVILEGE);
        }
        if (giftCard.getCouponId() != null) {
            Coupon coupon = couponDao.getByCouponId(giftCard.getCouponId());
            if (coupon == null || !coupon.getAccountId().equals(giftCard.getAccountId())) {
                throw new BaseException(SystemCodeEnum.NOT_EXIST);
            }
        }
        if (giftCard.getGiftcardId() != null) {
            GiftCard giftCard1 = giftCardDao.getById(giftCard.getGiftcardId());
            if (giftCard1 != null) {
                giftCardDao.update(giftCard);
                return;
            }
        }
        //String cardNO = NumberUtils.buildRandom(10);
        String cardNO = DateTimeUtil.getYYYYMMDDHHSS() + NumberUtils.buildRandom(4);
        giftCard.setCreateTime(new Date());
        giftCard.setCardNO(cardNO);
        giftCardDao.insertUP(giftCard);

        // 插入用户操作日志
        userOpLogService.insertSingle(UserOpLog.builder()
                .accountId(giftCard.getAccountId())
                .opUser(loginInfo.getName())
                .opUserPhone(loginInfo.getPhone())
                .operation("礼品卡变动")
                .opType("创建")
                .opPlatform(OperationPlatform.MANAGER.code)
                .opTime(LocalDateTime.now())
                .result(true)
                .build());
    }

    @Override
    public List<GiftCardVO> queryPage(LoginInfo loginInfo, Integer accountId, Integer pageNO, Integer rowCount, String sortName, String cardNO,
                                      Long startTime, Long endTime, Integer userId, Integer cardType) {
        if (!purviewService.purviewCheck(loginInfo.id, accountId)) {
            throw new BaseException(SystemCodeEnum.NO_PRIVILEGE);
        }
        Map<String, Object> params = new HashMap<>();
        params.put("accountId", accountId);
        params.put("start", (pageNO - 1) * rowCount);
        params.put("rowCount", rowCount);
        params.put("sortName", sortName);
        params.put("cardNO", cardNO);
        params.put("userId", userId);
        params.put("cardType", cardType);
        params.put("startTime", Optional.ofNullable(startTime).map(Date::new).orElse(null));
        params.put("endTime", Optional.ofNullable(endTime).map(Date::new).orElse(null));
        List<GiftCardVO> giftCards = giftCardDao.queryPage(params);

        //展示属性添加
        for (GiftCardVO giftCard : giftCards) {
            if (giftCard.getUserId() == null) {
                giftCard.setState(0);
            } else {
                giftCard.setState(1);

                User user = userService.getByUserId(giftCard.getUserId());
                if (user != null) {
                    giftCard.setPhone(user.getPhone());
                    GiftCardUser giftCardUser = giftCardUserService.getByUser(accountId, giftCard.getUserId());
                    if (giftCardUser != null) {
                        giftCard.setAmount(giftCardUser.getMoney());
                    }
                }
            }
        }

        return giftCards;
    }

    @Override
    public Integer queryCount(Integer accountId, String cardNO, Long startTime, Long endTime, Integer userId, Integer cardType) {
        return giftCardDao.getTotal(accountId, cardNO,
                Optional.ofNullable(startTime).map(Date::new).orElse(null),
                Optional.ofNullable(endTime).map(Date::new).orElse(null),
                userId, cardType);
    }

    @Override
    public List<GiftCard> queryPageByPhone(LoginInfo loginInfo, Integer accountId, Integer userId, Integer pageNO,
                                           Integer rowCount, String sortName, String sign, String cardNO, Long startTime, Long endTime) {
        Map<String, Object> params = new HashMap<>(16);
        params.put("accountId", accountId);
        params.put("userId", userId);
        params.put("start", (pageNO - 1) * rowCount);
        params.put("rowCount", rowCount);
        params.put("cardNO", cardNO);
        params.put("startTime", Optional.ofNullable(startTime).map(Date::new).orElse(null));
        params.put("endTime", Optional.ofNullable(endTime).map(Date::new).orElse(null));
        if (sortName != null) {
            params.put("sortName", sortName + " " + sign);
        }
        List<GiftCard> giftCards = giftCardDao.queryPageByUser(params);
        if (CollectionUtils.isNotEmpty(giftCards)) {
            for (GiftCard giftCard : giftCards) {
                if (giftCard.getUserId() == null) {
                    giftCard.setState(0);
                } else {
                    giftCard.setState(1);
                }
                Account account = accountService.getById(giftCard.getAccountId());
                giftCard.setAccountName(account.getName());
            }
        }
        return giftCards;
    }

    @Override
    public Integer selectTotalCount(Integer accountId, Integer userId, String cardNo, Long startTime, Long endTime) {
        Map<String, Object> params = new HashMap<>(8);
        params.put("accountId", accountId);
        params.put("userId", userId);
        params.put("cardNO", cardNo);
        params.put("startTime", Optional.ofNullable(startTime).map(Date::new).orElse(null));
        params.put("endTime", Optional.ofNullable(endTime).map(Date::new).orElse(null));
        return giftCardDao.getTotalByUser(params);
    }

    @Override
    public Result<List<GiveRideCardVo>> batchSendGiftCard(GiftCardBatchUpdateDTO giftCardBatchUpdateDTO) {
        giftCardBatchUpdateDTO.valid();
        final Integer accountId = giftCardBatchUpdateDTO.getAccountId();
        final Integer modifyMoney = giftCardBatchUpdateDTO.getMoney();
        final String remark = giftCardBatchUpdateDTO.getRemark();
        Set<String> userPhoneSet = giftCardBatchUpdateDTO.getUserPhones();

        String type = modifyMoney < 0 ? "扣款" : "充值";
        Map<String, User> userMap = userService.mapByUserPhone(userPhoneSet, accountService.getBrandIdByAccountId(accountId, 3));
        List<Usermsg> userMessageList = new ArrayList<>();
        List<GiveRideCardVo> failList = new ArrayList<>();
        GiveRideCardVo giveRideCardVo = null;
        for (String userPhone : userPhoneSet) {
            giveRideCardVo = new GiveRideCardVo();
            User user = userMap.get(userPhone);
            if (Objects.isNull(user)) {
                giveRideCardVo.setPhone(userPhone);
                giveRideCardVo.setFailMsg("用户不存在");
                failList.add(giveRideCardVo);
                continue;
            }
            try {
                giftCardUserService.recharge(accountId, user.getUserId(), modifyMoney, remark, giftCardBatchUpdateDTO.getLoginInfo());
            } catch (Exception e) {
                giveRideCardVo.setPhone(userPhone);
                giveRideCardVo.setFailMsg(e.getMessage());
                failList.add(giveRideCardVo);
                continue;
            }
            userMessageList.add(new Usermsg(user.getUserId(), String.format("礼品卡人工%s", type), String.format("礼品卡人工%s%d元,原因:%s", type, Math.abs(modifyMoney) / 100,
                    remark)));
        }
        //通知用户。
        if (CollectionUtils.isNotEmpty(userMessageList)) {
            usermsgDao.insertBatch(userMessageList);
        }
        return Result.success(failList);
    }

    private Map<String, Object> initParamMap(Integer userId, String cardNo) {
        String paramA = "youqu";
        long date = System.currentTimeMillis();
        String sign = MD5PasswordUtil.MD5("TBIT" + date + paramA);
        Map<String, Object> paramMap = new HashMap<>(8);
        paramMap.put("userId", userId);
        paramMap.put("cardNO", cardNo);
        paramMap.put("date", date);
        paramMap.put("param", paramA);
        paramMap.put("sign", sign);
        return paramMap;
    }

    @Override
    public List<String> addBatch(GiftCard giftCard, int num) {
        if (giftCard.getCouponId() != null) {
            Coupon coupon = couponDao.getByCouponId(giftCard.getCouponId());
            if (coupon == null || !coupon.getAccountId().equals(giftCard.getAccountId())) {
                throw new BaseException(SystemCodeEnum.NOT_EXIST);
            }
        }
        List<GiftCard> giftCards = new ArrayList<>();
        List<String> list = generateGiftCardExchangeCode(num);
        Date date = new Date();
        for (String carNO : list) {
            GiftCard card = new GiftCard();
            card.setCardNO(carNO);
            card.setCreateTime(date);
            card.setCardType(giftCard.getCardType());
            card.setMoney(giftCard.getMoney());
            card.setCouponId(giftCard.getCouponId());
            card.setCouponCount(giftCard.getCouponCount());
            card.setCouponExpireDays(giftCard.getCouponExpireDays());
            card.setExpireDate(giftCard.getExpireDate());
            card.setMemberFeeDays(giftCard.getMemberFeeDays());
            card.setAccountId(giftCard.getAccountId());
            card.setRemark("运营商批量生成");
            giftCards.add(card);
        }
        giftCardDao.addBatch(giftCards);

        // 插入用户操作日志
        UserInfo loginInfo = BaseController.fetchUserInfo();
        userOpLogService.insertSingle(UserOpLog.builder()
                .accountId(giftCard.getAccountId())
                .opUser(loginInfo.getName())
                .opUserPhone(loginInfo.getPhone())
                .operation("礼品卡变动")
                .opType("创建")
                .opPlatform(OperationPlatform.MANAGER.code)
                .opTime(LocalDateTime.now())
                .result(true)
                .detail("批量创建数量: " + num)
                .build());
        return list;
    }

    private List<String> generateGiftCardExchangeCode(Integer createNum) {
        while (true) {
            List<String> cardNos = getCarNOs(createNum);
            //已存在编号
            List<String> existNoList = giftCardDao.getByNOs(cardNos);
            if (CollectionUtils.isEmpty(existNoList)) {
                return cardNos;
            }
        }
    }

    /**
     * 生成礼品卡卡编号
     *
     * @param num
     * @return
     */
    private List<String> getCarNOs(Integer num) {
        List<String> list = new LinkedList<>();
        /**生成订单号*/
        for (int i = 0; i < num; i++) {
            String carNO = DateTimeUtil.getYYYYMMDDHHSS() + NumberUtils.buildRandom(8);
            while (list.contains(carNO)) {
                carNO = DateTimeUtil.getYYYYMMDDHHSS() + NumberUtils.buildRandom(8);
            }
            list.add(carNO);
        }
        return list;
    }

    public static void main(String[] args) {
        List<String> list = new LinkedList<>();
        /**生成订单号*/
        for (int i = 0; i < 2000; i++) {
            String carNO = DateTimeUtil.getYYYYMMDDHHSS() + NumberUtils.buildRandom(8);
            while (list.contains(carNO)) {
                carNO = DateTimeUtil.getYYYYMMDDHHSS() + NumberUtils.buildRandom(8);
            }
            list.add(carNO);
        }
        System.out.println(JSON.toJSONString(list));
    }
}
